package com.example.designpattern.c05_proxy.example02JDK动态代理;

import com.example.designpattern.c05_proxy.example01JDK静态代理.IUserDao;
import com.example.designpattern.c05_proxy.example01JDK静态代理.UserDaoImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 代理工厂类-动态的生成代理对象
 *
 * @author spikeCong
 * @date 2022/9/22
 **/
public class ProxyFactory {

    //维护一个目标对象
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    //为目标对象生成代理对象
    public Object getProxyInstance() {

        //使用proxy获取代理对象
        return Proxy.newProxyInstance(
                //目标类使用的类加载器
                target.getClass().getClassLoader(),
                //目标对象实现的接口类型
                target.getClass().getInterfaces(),
                new InvocationHandler() { //事件处理器

                    /**
                     * invole方法参数说明
                     * @param proxy 代理对象
                     * @param method  对应于在代理对象上面调用的接口方法实例
                     * @param args  代理对象调用接口对象是传递的实际参数
                     * @return java.lang.object返回目标对象方法的返回值，没有返回值就返回null
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        System.out.println("开启事务");
                        //invoke target's method
                        method.invoke(target, args);
                        System.out.println("提交事务");
                        return null;
                    }
                }
        );
    }

    /**
     * 静态代理测试
     * @param args
     */
    public static void main(String[] args) {
        UserDaoImpl target = new UserDaoImpl();
        //输出目标对象的信息
        System.out.println(target.getClass());
        //获取代理对象 这里只能以接口对象接受
        IUserDao proxy =  (IUserDao) new ProxyFactory(target).getProxyInstance();
        //print info of proxy
        System.out.println(proxy.getClass());
        //execute method
        proxy.save();

    }

}
